package com.myself.basic.gateway.filter;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;

import com.myself.basic.gateway.security.config.IgnoreUriListConfig;
import com.myself.common.define.model.CommonResult;
import com.myself.common.define.util.CustomJwtUtil;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatusCode;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.netty.ByteBufFlux;

import java.nio.charset.StandardCharsets;
import java.util.List;

/**
 * @author 瑟瑟发抖
 * @version 1.0
 * @description Token认证过滤器
 * @date 2024/4/9 11:39
 */

@Data
@Component
@AllArgsConstructor
public class CheckTokenFilter implements GlobalFilter {


    private final IgnoreUriListConfig ignoreUriListConfig;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
        String uri = request.getPath().toString();
        HttpHeaders headers = request.getHeaders();
        String failMessage = "未携带Token";

        //判断uri
        if (ignoreUriListConfig.getIgnoreUris().contains(uri)) {
            return chain.filter(exchange);
        }

        List<String> refreshTokenHeard = headers.get("RefreshToken");
        List<String> accessTokenHeard = headers.get("AccessToken");

        if (refreshTokenHeard != null && refreshTokenHeard.size() == 1 && refreshTokenHeard.get(0).startsWith("Bearer ")) {
            String refreshToken = refreshTokenHeard.get(0).replace("Bearer ", "");
            Boolean aBoolean = CustomJwtUtil.verifyRefreshToken(refreshToken);
            if (!aBoolean) {
                failMessage = "刷新Token已过期 请重新登录";
                response.setStatusCode(HttpStatusCode.valueOf(441));
                return response.writeAndFlushWith(Flux.just(ByteBufFlux.just(response.bufferFactory().wrap(JSONUtil.toJsonStr(CommonResult.fail(failMessage)).getBytes(StandardCharsets.UTF_8)))));

            }

        }

        if (accessTokenHeard != null && accessTokenHeard.size() == 1 && accessTokenHeard.get(0).startsWith("Bearer ")) {
            String accessToken = accessTokenHeard.get(0).replace("Bearer ", "");
            Boolean aBoolean = CustomJwtUtil.verifyAccessToken(accessToken);
            if (aBoolean) {
                //加入请求头 剩下服务无需解析
                JSONObject userInfo = CustomJwtUtil.parseToken(accessToken);
                ServerHttpRequest addRequest = exchange.getRequest().mutate().header("UserInfo", JSONUtil.toJsonStr(userInfo)).build();
                exchange = exchange.mutate().request(addRequest).build();
                return chain.filter(exchange);
            }
            failMessage = "认证Token已过期 请重新获取";
            response.setStatusCode(HttpStatusCode.valueOf(442));
        } else {
            failMessage = "认证Token已过期 请重新获取";
            response.setStatusCode(HttpStatusCode.valueOf(442));

        }

        //返回错误代码
        return response.writeAndFlushWith(Flux.just(ByteBufFlux.just(response.bufferFactory().wrap(JSONUtil.toJsonStr(CommonResult.fail(failMessage)).getBytes(StandardCharsets.UTF_8)))));
    }
}
